/' Copyright (c) 2007 Scott Lembcke
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 '/

 extern "C"
 
'' Collision begin event function callback type.
'' Returning false from a begin callback causes the collision to be ignored until
'' the the separate callback is called when the objects stop colliding.
type cpCollisionBeginFunc as function cdecl( byval as cpArbiter_ ptr, byval as cpSpace_ ptr, byval as any ptr ) as cpBool
'' Collision pre-solve event function callback type.
'' Returning false from a pre-step callback causes the collision to be ignored until the next step.
type cpCollisionPreSolveFunc as function cdecl( byval as cpArbiter_ ptr, byval as cpSpace_ ptr, byval as any ptr ) as cpBool
'' Collision post-solve event function callback type.
type cpCollisionPostSolveFunc as sub cdecl( byval as cpArbiter_ ptr, byval as cpSpace_ ptr, byval as any ptr )
'' Collision separate event function callback type.
type cpCollisionSeparateFunc as sub cdecl( byval as cpArbiter_ ptr, byval as cpSpace_ ptr, byval as any ptr )
 
type cpCollisionHandler
	as cpCollisionType			a
	as cpCollisionType			b
	as cpCollisionBeginFunc		begin
	as cpCollisionPreSolveFunc	preSolve
	as cpCollisionPostSolveFunc	postSolve
	as cpCollisionSeparateFunc	separate
	as any ptr					data
end type

type cpContact_ as cpContact

#define CP_MAX_CONTACTS_PER_ARBITER 4

enum cpArbiterState
	'' Arbiter is active and its the first collision.
	cpArbiterStateFirstColl
	'' Arbiter is active and its not the first collision.
	cpArbiterStateNormal
	'' Collision has been explicitly ignored.
	'' Either by returning false from a begin collision handler or calling cpArbiterIgnore().
	cpArbiterStateIgnore
	'' Collison is no longer active. A space will cache an arbiter for up to cpSpace.collisionPersistence more steps.
	cpArbiterStateCached
end enum

type cpArbiterThread
	'' Links to next and previous arbiters in the contact graph.
	as cpArbiter_ ptr	next, prev
end type

'' A colliding pair of shapes.
type cpArbiter
	'' Calculated value to use for the elasticity coefficient.
	'' Override in a pre-solve collision handler for custom behavior.
	as cpFloat			e
	'' Calculated value to use for the friction coefficient.
	'' Override in a pre-solve collision handler for custom behavior.
	as cpFloat			u
	'' Calculated value to use for applying surface velocities.
	'' Override in a pre-solve collision handler for custom behavior.
	as cpVect			surface_vr
	
	as cpShape_ ptr		a
	as cpShape_ ptr		b
	as cpBody_ ptr		body_a
	as cpBody_ ptr		body_b
	
	as cpArbiterThread	thread_a
	as cpArbiterThread	thread_b
	
	as integer			numContacts
	as cpContact_ ptr	contacts
	
	as cpTimestamp		stamp
	as cpCollisionHandler ptr handler
	as cpBool			swappedColl
	as cpArbiterState	state
end type

#define CP_DefineArbiterStructGetter(t, member, n) function cpArbiterGet##n cdecl( byval arb as const cpArbiter ptr ) as t : return arb->member : end function

#define CP_DefineArbiterStructSetter(t, member, n) sub cpArbiterSet##n cdecl( byval arb as cpArbiter ptr, byval value as t ) : arb->member = value : end sub

#macro CP_DefineArbiterStructProperty(t, member, n)
CP_DefineArbiterStructGetter(t, member, n)
CP_DefineArbiterStructSetter(t, member, n)
#endmacro

CP_DefineArbiterStructProperty(cpFloat, e, Elasticity)
CP_DefineArbiterStructProperty(cpFloat, u, Friction)
CP_DefineArbiterStructProperty(cpVect, surface_vr, SurfaceVelocity)

'' Calculate the total impulse that was applied by this arbiter.
'' Calling this function from a begin or pre-solve callback is undefined.
declare function cpArbiterTotalImpulse ( byval as const cpArbiter ptr ) as cpVect
'' Calculate the total impulse including the friction that was applied by this arbiter.
'' Calling this function from a begin or pre-solve callback is undefined.
declare function cpArbiterTotalImpulseWithFriction ( byval as const cpArbiter ptr ) as cpVect

'' Causes a collision pair to be ignored as if you returned false from a begin callback.
'' If called from a pre-step callback, you will still need to return false
'' if you want it to be ignored in the current step.
declare sub cpArbiterIgnore ( byval as cpArbiter ptr )

'' Return the colliding shapes involved for this arbiter.
'' The order of their cpSpace.collision_type values will match
'' the order set when the collision handler was registered.
sub cpArbiterGetShapes cdecl( byval arb as const cpArbiter ptr, byval a as cpShape_ ptr ptr, byval b as cpShape_ ptr ptr )
	if arb->swappedColl then
		*a = arb->b
		*b = arb->a
	else
		*a = arb->a
		*b = arb->b
	end if
end sub

'' A macro shortcut for defining and retrieving the shapes from an arbiter.
#define CP_ARBITER_GET_SHAPES(arb, a, b) dim as cpShape_  ptr a, b : cpArbiterGetShapes(arb, @a, @b)

'' Return the colliding bodies involved for this arbiter.
'' The order of the cpSpace.collision_type the bodies are associated with values will match
'' the order set when the collision handler was registered.
sub cpArbiterGetBodies cdecl( byval arb as const cpArbiter ptr, byval a as cpBody_ ptr ptr, byval b as cpBody_ ptr ptr )
	CP_ARBITER_GET_SHAPES( arb, shape_a, shape_b )
	*a = shape_a->body
	*b = shape_b->body
end sub

'' A macro shortcut for defining and retrieving the bodies from an arbiter.
#define CP_ARBITER_GET_BODIES(arb, a, b) dim as cpBody_ ptr a, b : cpArbiterGetBodies(arb, @a, @b);

'' Returns true if this is the first step a pair of objects started colliding.
function cpArbiterIsFirstContact cdecl( byval arb as const cpArbiter ptr ) as cpBool
	return arb->state = cpArbiterStateFirstColl
end function

'' Get the number of contact points for this arbiter.
function cpArbiterGetCount cdecl( byval arb as const cpArbiter ptr ) as integer
	return arb->numContacts
end function

'' * FreeBASIC Note: Freebasic does not support inline
'' structures/UDTs, so I had to create my own UDT.
type cpContactPoint_
	'' The position of the contact point.
	as cpVect point
	'' The normal of the contact point.
	as cpVect normal
	'' The depth of the contact point.
	as cpFloat dist
end type

'' A struct that wraps up the important collision data for an arbiter.
type cpContactPointSet
	'' The number of contact points in the set.
	as integer count
	
	'' The array of contact points.
	as cpContactPoint_	points(0 To CP_MAX_CONTACTS_PER_ARBITER-1)
end type
'' Return a contact set from an arbiter.
declare function cpArbiterGetContactPointSet ( byval as const cpArbiter ptr ) as cpContactPointSet

'' Get the normal of the @c ith contact point.
declare function cpArbiterGetNormal ( byval as const cpArbiter ptr, byval as integer ) as cpVect
'' Get the position of the @c ith contact point.
declare function cpArbiterGetPoint ( byval as const cpArbiter ptr, byval as integer ) as cpVect
'' Get the depth of the @c ith contact point.
declare function cpArbiterGetDepth ( byval as const cpArbiter ptr, byval as integer ) as cpFloat

end extern
